package cn.escco.ocr.service.impl;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.escco.ocr.dto.po.base.Base;
import cn.escco.ocr.service.BaseService;

/*
 * @Description 共通实现方法
 * @Author YOYO
 * @Date 2020-11-17 17:57
 */
@Transactional(rollbackFor = Exception.class)
public class BaseServiceImpl<MAPPER extends BaseMapper<T>, T extends Base> extends ServiceImpl<MAPPER, T> implements BaseService<T> {

    @Autowired
    public MAPPER baseDao;


    /**
     * 根据条件查询分页数据
     *
     * @param t po.
     * @return List<T>
     */
    @Override
    public List<T> findAll(T t) {
        Wrapper<T> queryWrapper = getQueryWrapper(t);
        if (ObjectUtils.isEmpty(t))
            return baseDao.selectList(null);
        else
            return baseDao.selectList(queryWrapper);
    }

    /**
     * 根据条件查询分页数据
     *
     * @param page      page
     * @param condition .
     * @return Page<T>
     */
    @Override
    public Page<T> findAll(Page<T> page, T condition) {
        return findAllOfEq(page, condition);
    }

    /**
     * 插入 or 更新
     *
     * @param t po
     */
    void save(T t, String... cols) {

        T rt = findOne(t, cols);

        if (ObjectUtils.isEmpty(rt))
            baseDao.insert(t);
        else
            baseDao.update(t, getUpdateClassId(t));
    }

    /**
     * 查询一条数据
     *
     * @param t    po
     * @param cols columns
     * @return T extend Base
     */
    public T findOne(T t, String... cols) {
        Wrapper<T> queryWrapper = getQueryWrapper(t, cols);
        return baseDao.selectOne(queryWrapper);
    }

    /**
     * 根据条件查询所有数据
     *
     * @param t    po
     * @param cols columns
     * @return T extend Base
     */
    List<T> findAll(T t, String... cols) {
        Wrapper<T> queryWrapper = getQueryWrapper(t, cols);
        return baseDao.selectList(queryWrapper);
    }

    /**
     * 根据入参分页查询数据
     *
     * @param page Page
     * @param t    po
     * @return Page
     */
    Page<T> findAllOfLike(Page<T> page, T t) {

        QueryWrapper<T> queryWrapper = getQueryWrapperOfLike(t);
        if (ObjectUtils.isEmpty(t))
            return baseDao.selectPage(page, null);
        else
            return baseDao.selectPage(page, queryWrapper);
    }

    /**
     * 根据入参分页查询数据
     *
     * @param page Page
     * @param t    po
     * @return Page
     */
    Page<T> findAllOfEq(Page<T> page, T t) {
        Wrapper<T> queryWrapper = getQueryWrapper(t);
        return baseDao.selectPage(page, queryWrapper);
    }

    /**
     * 获取实体主键值并封装为 and 更新语句
     *
     * @param t po
     * @return UpdateWrapper
     */
    private UpdateWrapper<T> getUpdateClassId(T t) {

        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        Field[] fields = t.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                if (!ObjectUtils.isEmpty(field)) {
                    field.setAccessible(true);
                    TableId idField = field.getDeclaredAnnotation(TableId.class);
                    //主键
                    if (!ObjectUtils.isEmpty(field.get(t)) && !ObjectUtils.isEmpty(idField))
                        updateWrapper.eq(idField.value(), field.get(t));
                }
            }
        } catch (IllegalAccessException e) {
            System.out.println("------");
        }
        return updateWrapper;
    }

    /**
     * 获取实体主键值并封装为 and 更新语句
     *
     * @param t po
     * @return UpdateWrapper
     */
    private QueryWrapper<T> getQueryClassId(T t) {

        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        Field[] fields = t.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                if (!ObjectUtils.isEmpty(field)) {
                    field.setAccessible(true);
                    TableId idField = field.getDeclaredAnnotation(TableId.class);
                    //主键
                    if (!ObjectUtils.isEmpty(field.get(t)) && !ObjectUtils.isEmpty(idField))
                        queryWrapper.eq(idField.value(), field.get(t));
                }
            }
        } catch (IllegalAccessException e) {
            System.out.println("------");
        }
        return queryWrapper;
    }

    /**
     * 封装更新 sql (指定更新字段)
     *
     * @param t    po
     * @param cols columns
     * @return UpdateWrapper
     */
    protected UpdateWrapper<T> getUpdateWrapper(T t, String... cols) {

        if (ObjectUtils.isEmpty(t))
            return null;

        UpdateWrapper<T> updateWrapper = null;
        Field field;
        try {
            updateWrapper = new UpdateWrapper<>(t);
            //更新属性
            for (String col : cols) {
                field = t.getClass().getDeclaredField(col);

                if (!ObjectUtils.isEmpty(field)) {
                    field.setAccessible(true);
                    TableField tableField = field.getDeclaredAnnotation(TableField.class);
                    updateWrapper.eq(tableField.value(), field.get(t));
                }
            }

        } catch (NoSuchFieldException | IllegalAccessException e) {
            System.out.println("------");
        }
        return updateWrapper;
    }

    /**
     * 封装 and 查询语句
     *
     * @param t    po
     * @param cols columns
     * @return QueryWrapper
     */
    private QueryWrapper<T> getQueryWrapper(T t, String... cols) {

        QueryWrapper<T> queryWrapper = null;
        Field field;
        try {
            if (!CollectionUtils.isEmpty(Arrays.asList(cols))) {

                queryWrapper = new QueryWrapper<>();

                for (String col : cols) {
                    field = t.getClass().getDeclaredField(col);

                    if (!ObjectUtils.isEmpty(field)) {
                        field.setAccessible(true);
                        TableField tableField = field.getDeclaredAnnotation(TableField.class);
                        queryWrapper.eq(tableField.value(), field.get(t));
                    }
                }
            } else {
                queryWrapper = getQueryClassId(t);
                queryWrapper.setEntity(t);
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            System.out.println("------");
        }
        return queryWrapper;
    }

    /**
     * 封装 and 查询语句
     *
     * @param t po
     * @return QueryWrapper
     */
    private QueryWrapper<T> getQueryWrapperOfLike(T t) {

        if (ObjectUtils.isEmpty(t))
            return null;

        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        Field[] fields = t.getClass().getDeclaredFields();

        try {
            for (Field field : fields) {
                if (!ObjectUtils.isEmpty(field)) {
                    field.setAccessible(true);
                    TableId idField = field.getDeclaredAnnotation(TableId.class);
                    TableField tableField = field.getDeclaredAnnotation(TableField.class);

                    //主键
                    if (!ObjectUtils.isEmpty(field.get(t)) && !ObjectUtils.isEmpty(idField))
                        queryWrapper.eq(idField.value(), field.get(t));

                    queryWrapper.or();

                    //成员
                    if (!ObjectUtils.isEmpty(field.get(t)) && !ObjectUtils.isEmpty(tableField))
                        queryWrapper.like(tableField.value(), field.get(t));
                }
            }
        } catch (IllegalAccessException e) {
            System.out.println("------");
        }
        return queryWrapper;
    }

}
